import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { Observable, of, throwError } from 'rxjs'
import { switchMap, catchError } from 'rxjs/operators'
import { SettingsService } from '@delon/theme'

import { ISearchOption } from '@shared/interfaces/search'
import { StoreService } from 'app/routes/store/store.service'
import { EUserType, ETradeChannel } from '@shared/enums'
import { I18NService } from '@core'
import { AcquirerService } from 'app/routes/acquirer/acquirer.service'
import { StoreFull } from '@shared/interfaces/store'
import { Acquirer } from '@shared/interfaces/acquirer'
import { IChannelQueryParams, Channel } from '@shared/interfaces/channel'
import { IGenericPagination } from '@shared/interfaces/pagination'
import { COMB_URL } from 'app/utils/contraints'
import { channelOptionSort, filterChannel } from 'app/utils/helpers'

@Injectable({
  providedIn: 'root',
})
export class ChannelService {

  constructor(
    private i18n: I18NService,
    private storeService: StoreService,
    private acquirerService: AcquirerService,
    private settingService: SettingsService,
    private http: HttpClient,
  ) {}

  public getCurrentSupportChannelOptions(): Observable<ISearchOption[]> {
    const { userType, intStoreCode, insCode } = this.settingService.user
    if (userType === EUserType.CIL || userType === EUserType.GenAdmin) {
      /** admin, return all */
      return of(Object.keys(ETradeChannel).map(key => ({
        label: this.trans(ETradeChannel[key]),
        value: key,
      })).sort(channelOptionSort))
    }

    if (userType === EUserType.Store) {
      /** store user return store channels */
      return this.storeService.getOne(intStoreCode).pipe(
        switchMap((storeFull: StoreFull) => {
          const { qrChannels, cardChannels, ecPayChannels } = storeFull
          const channels = [...qrChannels, ...cardChannels, ...ecPayChannels]
          const chanCodes = [...new Set(filterChannel(channels.map(c => c.chanCode)))]
          return of(
            chanCodes.map(code => ({
              label: this.trans(ETradeChannel[code]),
              value: code,
            })).sort(channelOptionSort)
          )
        })
      )
    }
    /** other user, return Institution Channels */
    return this.acquirerService.getOne(insCode).pipe(
      switchMap((acquirer: Acquirer) => {
        const { qrChannels, cardChannels, ecPayChannels } = acquirer
        const channels = [...qrChannels, ...cardChannels, ...ecPayChannels]
        const chanCodes = [...new Set(filterChannel(channels.map(c => c.chanCode)))]
        return of(
          chanCodes.map(code => ({
            label: this.trans(ETradeChannel[code]),
            value: code,
          })).sort(channelOptionSort)
        )
      })
    )
  }

  paging(query: IChannelQueryParams): Observable<IGenericPagination<Channel>> {
    const q = Object.keys(query)
      .filter(key => !!query[key])
      .map(key => `${key}=${query[key]}`)
      .join('&')
    let url = `${COMB_URL}/camel/channel/merchants`
    if (q) {
      url += `?${q}`
    }

    return this.http.get<IGenericPagination<Channel>>(url, {}).pipe(
      catchError(err => {
        return throwError(err)
      }),
    )
  }

  public trans(str: string): string {
    return this.i18n.fanyi(str)
  }
}
